﻿using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Sino.CapacityCloud.Infrastructure.Events;
using Sino.CapacityCloud.Repositories.Models;
using Sino.CapacityCloud.WebApi;
using Sino.Tms.Primitives;
using Sino.TMSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sino.CapacityCloud.Services
{

    public class CarManager
    {

        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger _logger;
        private readonly IEventBus _eventBus;

        public CarManager(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IEventBus eventBus)
        {
            this._logger = loggerFactory.CreateLogger<CarManager>();
            this._serviceProvider = serviceProvider;
            this._eventBus = eventBus;
        }

        public string AddOrUpdateCarInfo(string carCode, CarLength? carLength = null, CarriageType? carriageType = null, VehicleType? vehicleType = null, CarDetails carDetails = null, string carCommiterId = null, double? assignmentOfLoad = null, string origin = null)
        {
            try
            {
                using (var serviceScope = this._serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
                {
                    using (var dbContext = serviceScope.ServiceProvider.GetService<ApplicationDbContext>())
                    {
                        var car = dbContext.Cars.FirstOrDefault(x => x.Code == carCode);
                        if (car == null)
                        {
                            car = new Repositories.Models.Car()
                            {
                                Date = DateTime.Now,
                                AssignmentOfLoad = carDetails?.AuthorizedLoad ?? assignmentOfLoad ?? 0.0f,
                                AddingCommitId = carCommiterId,
                                Code = carCode,
                                Length = carLength ?? CarLength.None,
                                CarriageType = carriageType ?? CarriageType.None,
                                Origin = carDetails?.Origin ?? origin,
                                Type = vehicleType ?? VehicleType.None,
                                TrailerLicenseKey = carDetails?.TrailerLicenseKey,
                                TrailerLicenseCertificationStatus = carDetails?.TrailerLicenseKey != null ? CertificationStatus.Passed : CertificationStatus.None,
                                VehicleLicenseKey = carDetails?.VehicleLicenseKey,
                                CertificationStatus = carDetails?.VehicleLicenseKey != null ? CertificationStatus.Passed : CertificationStatus.None,
                                VehiclePhotoKey = carDetails?.VehiclePhotoKey,
                                VehiclePhotoCertificationStatus = carDetails?.VehiclePhotoKey != null ? CertificationStatus.Passed : CertificationStatus.None,
                            };
                            dbContext.Cars.Add(car);
                            dbContext.SaveChanges();
                            if (carDetails != null && carDetails.Users?.Count > 0)
                            {
                                var eventData = Mapper.Map(car, new CarAddEventData());
                                foreach (var user in carDetails.Users)
                                {
                                    eventData.Driver = user.RealName;
                                    eventData.DriverPhone = user.PhoneNumber;
                                    this._eventBus.Post(eventData, TimeSpan.Zero);
                                }
                            }
                        }
                        else
                        {
                            if (!string.IsNullOrWhiteSpace(carCommiterId) && string.IsNullOrWhiteSpace(car.AddingCommitId))
                            {
                                car.AddingCommitId = carCommiterId;
                            }
                            if (car.AssignmentOfLoad <= 0)
                            {
                                car.AssignmentOfLoad = carDetails?.AuthorizedLoad ?? assignmentOfLoad ?? 0.0f;
                            }
                            if (car.Length == CarLength.None)
                            {
                                car.Length = carLength ?? car.Length;
                            }
                            if (car.CarriageType == CarriageType.None)
                            {
                                car.CarriageType = carriageType ?? car.CarriageType;
                            }
                            if (car.Type == VehicleType.None)
                            {
                                car.Type = vehicleType ?? car.Type;
                            }
                            if (!string.IsNullOrWhiteSpace(car.Origin))
                            {
                                car.Origin = carDetails?.Origin ?? origin;
                            }
                            if (string.IsNullOrWhiteSpace(car.TrailerLicenseKey))
                            {
                                car.TrailerLicenseKey = carDetails?.TrailerLicenseKey;
                                car.TrailerLicenseCertificationStatus = carDetails?.TrailerLicenseKey != null ? CertificationStatus.Passed : CertificationStatus.None;
                            }
                            if (string.IsNullOrWhiteSpace(car.VehicleLicenseKey))
                            {
                                car.VehicleLicenseKey = carDetails?.VehicleLicenseKey;
                                car.CertificationStatus = carDetails?.VehicleLicenseKey != null ? CertificationStatus.Passed : CertificationStatus.None;
                            }
                            if (string.IsNullOrWhiteSpace(car.VehiclePhotoKey))
                            {
                                car.VehiclePhotoKey = carDetails?.VehiclePhotoKey;
                                car.VehiclePhotoCertificationStatus = carDetails?.VehiclePhotoKey != null ? CertificationStatus.Passed : CertificationStatus.None;
                            }
                            dbContext.SaveChanges();
                        }
                        return car.CarId;
                    }
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError("Failed to add or update a car from EventBus.", ex);
                throw;
            }
        }

    }

}